﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

using agree.schema;
using agree.mrs;

using alib;
using alib.BitArray;
using alib.Collections;
using alib.Collections.ReadOnly;
using alib.Combinatorics;
using alib.Debugging;
using alib.Enumerable;
using alib.Reflection;
using alib.String;

namespace agree.transfer
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	[DebuggerDisplay("hyp #{id}  {tgt_rels.ToString(),nq}")]
	public class Hypothesis : identity_base, IEnumerable<RuleApplication>, ISemantics
	{
		public Hypothesis(TransferExecutor te, Relation[] locus)
			: base(te)
		{
			this.id = Interlocked.Increment(ref te.next_hyp_id) - 1;
			this.LOCUS.a = locus;
			TransferExecutor.dbg_writeline("new hyp #{0}", id);
		}
		public Hypothesis(TransferExecutor prv, Hypothesis h_old, RuleApplication ra)
			: this(prv, h_old.LOCUS.a)
		{
			this.parent_hyp = h_old;
			this.ra = ra;
		}
		public readonly long id;

		public readonly RuleApplication ra;

		public Hypothesis parent_hyp;

		public bag<Relation> LOCUS;


		public bool Contains(TransferRule r_seek)
		{
			TransferRule r;
			var h = this;
			do
				if ((r = h.ra.rule) == r_seek)
					return true;
			while ((h = h.parent_hyp) != null);
			return false;
		}
		public bool Contains(RuleApplication ra_seek)
		{
			var h = this;
			do
				if (h.ra.Equals(ra_seek))
					return true;
			while ((h = h.parent_hyp) != null);
			return false;
		}

		public IEnumerator<RuleApplication> GetEnumerator()
		{
			for (var h = this; h.ra.rule != null; h = h.parent_hyp)
				yield return h.ra;
		}

		IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

		public String Report()
		{
			StringBuilder sb = new StringBuilder();
			foreach (Relation loc in LOCUS)
				sb.Append(loc.ToString());
			sb.AppendLine();
			foreach (var ra in this.Reverse())
				sb.AppendLine(String.Format("{0}", ra.ToString()));
			return sb.ToString();
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// 
		public void show_hyp()
		{
			xfer_ext.dbg_writeline("--- hypothesis {0} ---", this.id);
			foreach (var ra in this.Reverse())
				xfer_ext.dbg_writeline("{0}", ra.ToString());

			LOCUS.show_rels();
		}

		public override String ToString()
		{
			return LOCUS.StringJoin(" ");
		}

		public Constant RegisterConstant(string value)
		{
			throw new NotImplementedException();
		}

		public Variable CreateInstance(System.Type sem_type)
		{
			throw new NotImplementedException();
		}

		public SemType GetSemType<T>() where T : SemType
		{
			throw new NotImplementedException();
		}
	};
}
